import fs from 'fs';
import path from 'path';
import rpg_component from '../../component/rpg_component';
import { PassiveTriggerType } from '../../shared/face/enums';
import { ComType } from '../tool/component';
import { env } from '../../config';

export interface BattleLogEntry {
  timestamp: string;
  type: 'action' | 'passive' | 'damage' | 'healing' | 'kill' | 'buff' | 'error' | 'info';
  message: string;
  data?: any;
}

export interface DetailedBattleLog {
  battleId: string;
  startTime: string;
  endTime?: string;
  duration: number;
  entries: BattleLogEntry[];
  participants: any[];
  result: any;
}

export interface RoundLog {
  roundNumber: number;
  startTime: string;
  endTime: string;
  duration: number;
  actions: ActionLog[];
  passiveTriggers: PassiveTriggerLog[];
  buffEffects: BuffEffectLog[];
  unitStates: UnitStateLog[];
}

export interface ActionLog {
  timestamp: string;
  actorId: string;
  actorName: string;
  actionType: 'attack' | 'skill' | 'passive' | 'buff';
  skillId?: string;
  skillName?: string;
  targetId?: string;
  targetName?: string;
  damage?: number;
  healing?: number;
  attackType?: string;
  penetration?: number;
  finalDamage?: number;
  targetHpBefore?: number;
  targetHpAfter?: number;
  targetDefense?: number;
  details: string;
}

export interface PassiveTriggerLog {
  timestamp: string;
  unitId: string;
  unitName: string;
  skillId: string;
  skillName: string;
  triggerType: PassiveTriggerType;
  conditionResult: boolean;
  conditionDetails: string;
  targets: string[];
  executed: boolean;
  reason?: string;
}

export interface BuffEffectLog {
  timestamp: string;
  unitId: string;
  unitName: string;
  buffId: string;
  buffName: string;
  effect: string;
  value: number;
}

export interface UnitStateLog {
  unitId: string;
  unitName: string;
  hp: number;
  maxHp: number;
  hpPercentage: number;
  isAlive: boolean;
  buffs: string[];
  skills: string[];
}

export interface ParticipantInfo {
  id: string;
  name: string;
  isHome: boolean;
  level: number;
  maxHp: number;
  attack: number;
  defense: number;
  skills: string[];
  initialHp: number;
}

export interface BattleResult {
  winner: 'home' | 'away' | 'draw';
  totalRounds: number;
  homeSurvivors: number;
  awaySurvivors: number;
  totalDamage: number;
  totalHealing: number;
}

export interface SkillTriggerLog {
  timestamp: string;
  skillId: string;
  skillName: string;
  triggerType: string;
  condition: string;
  result: boolean;
  reason: string;
}

export interface PassiveActivationLog {
  timestamp: string;
  unitId: string;
  skillId: string;
  skillName: string;
  triggerType: PassiveTriggerType;
  conditionResult: boolean;
  targets: string[];
  executed: boolean;
  reason?: string;
}

export interface DamageLog {
  timestamp: string;
  attackerId: string;
  attackerName: string;
  targetId: string;
  targetName: string;
  damage: number;
  attackType: string;
  penetration: number;
  targetDefense: number;
  finalDamage: number;
  targetHpBefore: number;
  targetHpAfter: number;
  isCritical: boolean;
  skillId?: string;
  skillName?: string;
}

export interface HealingLog {
  timestamp: string;
  healerId: string;
  healerName: string;
  targetId: string;
  targetName: string;
  healing: number;
  targetHpBefore: number;
  targetHpAfter: number;
  skillId?: string;
  skillName?: string;
}

export interface KillLog {
  timestamp: string;
  killerId: string;
  killerName: string;
  victimId: string;
  victimName: string;
  round: number;
  skillId?: string;
  skillName?: string;
  damage: number;
}

export interface BuffLog {
  timestamp: string;
  unitId: string;
  unitName: string;
  buffId: string;
  buffName: string;
  action: 'add' | 'remove' | 'update';
  value?: number;
  duration?: number;
}

export interface ErrorLog {
  timestamp: string;
  error: string;
  context: string;
  stack?: string;
}

export class BattleLogger {
  private logDir: string;
  private currentLog: DetailedBattleLog;
  private isLogging: boolean = false;

  constructor() {
    this.logDir = path.join(process.cwd(), 'battle_logs');
    this.ensureLogDirectory();
    this.currentLog = this.createNewLog();
  }

  private ensureLogDirectory(): void {
    if (!fs.existsSync(this.logDir)) {
      fs.mkdirSync(this.logDir, { recursive: true });
      // 删除目录下所有文件
    }
    const files = fs.readdirSync(this.logDir);
    files.forEach(file => {
      const filePath = path.join(this.logDir, file);
      fs.unlinkSync(filePath);
    });
  }

  private createNewLog(): DetailedBattleLog {
    return {
      battleId: `battle_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      startTime: new Date().toISOString(),
      duration: 0,
      entries: [],
      participants: [],
      result: {}
    };
  }

  startBattle(homeUnits: rpg_component[], awayUnits: rpg_component[]): void {
    this.isLogging = true;
    this.currentLog = this.createNewLog();
    
    this.log('info', '战斗开始', {
      homeUnits: homeUnits.length,
      awayUnits: awayUnits.length,
      totalUnits: homeUnits.length + awayUnits.length
    });
    
    // 记录参与者
    this.recordParticipants(homeUnits, awayUnits);
  }

  endBattle(winner: string, totalRounds: number): void {
    this.currentLog.endTime = new Date().toISOString();
    this.currentLog.duration = new Date(this.currentLog.endTime).getTime() - new Date(this.currentLog.startTime).getTime();
    
    this.currentLog.result = { winner, totalRounds };
    
    this.saveLog();
    this.isLogging = false;
    
    this.log('info', '战斗结束', { winner, totalRounds, duration: this.currentLog.duration });
  }

  log(type: BattleLogEntry['type'], message: string, data?: any): void {
    if (!this.isLogging) return;
    
    const entry: BattleLogEntry = {
      timestamp: new Date().toISOString(),
      type,
      message,
      data
    };
    
    this.currentLog.entries.push(entry);
    
  }

  logPassiveTrigger(unit: rpg_component, skillId: string, skillName: string, triggerType: PassiveTriggerType, conditionResult: boolean, executed: boolean, reason?: string): void {
    try {
      const baseCom = unit.getComponent(ComType.base) as any;
      this.log('passive', '被动技能触发', {
        unitId: unit.id,
        unitName: baseCom?.nickName || unit.id,
        skillId,
        skillName,
        triggerType,
        conditionResult,
        executed,
        reason
      });
    } catch (error: any) {
      this.log('error', '获取单位基础信息失败', { unitId: unit.id, error: error?.message || '未知错误' });
    }
  }

  logDamage(attacker: rpg_component, target: rpg_component, damage: number, attackType: string, finalDamage: number, skillId?: string): void {
    try {
      const attackerBase = attacker.getComponent(ComType.base) as any;
      const targetBase = target.getComponent(ComType.base) as any;
      
      this.log('damage', '伤害记录', {
        attackerId: attacker.id,
        attackerName: attackerBase?.nickName || attacker.id,
        targetId: target.id,
        targetName: targetBase?.nickName || target.id,
        damage,
        attackType,
        finalDamage,
        skillId,
        targetHpBefore: target.hp_now + finalDamage,
        targetHpAfter: target.hp_now
      });
    } catch (error: any) {
      this.log('error', '记录伤害失败', { 
        attackerId: attacker.id, 
        targetId: target.id, 
        error: error?.message || '未知错误' 
      });
    }
  }

  logHealing(healer: rpg_component, target: rpg_component, healing: number, skillId?: string): void {
    try {
      const healerBase = healer.getComponent(ComType.base) as any;
      const targetBase = target.getComponent(ComType.base) as any;
      
      this.log('healing', '治疗记录', {
        healerId: healer.id,
        healerName: healerBase?.nickName || healer.id,
        targetId: target.id,
        targetName: targetBase?.nickName || target.id,
        healing,
        skillId,
        targetHpBefore: target.hp_now - healing,
        targetHpAfter: target.hp_now
      });
    } catch (error: any) {
      this.log('error', '记录治疗失败', { 
        healerId: healer.id, 
        targetId: target.id, 
        error: error?.message || '未知错误' 
      });
    }
  }

  logKill(killer: rpg_component, victim: rpg_component, round: number, skillId?: string): void {
    try {
      const killerBase = killer.getComponent(ComType.base) as any;
      const victimBase = victim.getComponent(ComType.base) as any;
      
      this.log('kill', '击杀记录', {
        killerId: killer.id,
        killerName: killerBase?.nickName || killer.id,
        victimId: victim.id,
        victimName: victimBase?.nickName || victim.id,
        round,
        skillId
      });
    } catch (error: any) {
      this.log('error', '记录击杀失败', { 
        killerId: killer.id, 
        victimId: victim.id, 
        error: error?.message || '未知错误' 
      });
    }
  }

  logError(error: string, context: string): void {
    this.log('error', error, { context });
  }

  private recordParticipants(homeUnits: rpg_component[], awayUnits: rpg_component[]): void {
    const recordUnit = (unit: rpg_component, isHome: boolean) => {
      try {
        const baseCom = unit.getComponent(ComType.base) as any;
        return {
          id: unit.id,
          name: baseCom?.nickName || unit.id,
          isHome,
          level: unit.level,
          maxHp: unit.getAttribute('最大生命值'),
          attack: unit.getAttribute('攻击'),
          defense: unit.getAttribute('防御'),
          skills: unit.outSkills.map(skill => skill.skillId),
          initialHp: unit.hp_now
        };
      } catch (error: any) {
        this.log('error', '记录参与者信息失败', { 
          unitId: unit.id, 
          error: error?.message || '未知错误' 
        });
        return {
          id: unit.id,
          name: unit.id,
          isHome,
          level: unit.level,
          maxHp: 0,
          attack: 0,
          defense: 0,
          skills: [],
          initialHp: unit.hp_now
        };
      }
    };
    
    this.currentLog.participants = [
      ...homeUnits.map(unit => recordUnit(unit, true)),
      ...awayUnits.map(unit => recordUnit(unit, false))
    ];
  }

  private saveLog(): void {
    try {
      const fileName = `${this.currentLog.battleId}.json`;
      const filePath = path.join(this.logDir, fileName);
      
      fs.writeFileSync(filePath, JSON.stringify(this.currentLog, null, 2), 'utf8');
      
      // 只在开发模式下输出保存信息
      if (env.DEV) {
        console.log(`战斗日志已保存: ${filePath}`);
      }
      
    } catch (error) {
      console.error('保存战斗日志失败:', error);
    }
  }

  // 获取最近的战斗日志
  getRecentLogs(count: number = 10): string[] {
    try {
      const files = fs.readdirSync(this.logDir)
        .filter(file => file.endsWith('_simplified.json'))
        .sort((a, b) => {
          const statA = fs.statSync(path.join(this.logDir, a));
          const statB = fs.statSync(path.join(this.logDir, b));
          return statB.mtime.getTime() - statA.mtime.getTime();
        })
        .slice(0, count);
      
      return files.map(file => path.join(this.logDir, file));
    } catch (error) {
      console.error('获取战斗日志失败:', error);
      return [];
    }
  }

  // 读取特定战斗日志
  getBattleLog(battleId: string): DetailedBattleLog | null {
    try {
      const filePath = path.join(this.logDir, `${battleId}.json`);
      if (fs.existsSync(filePath)) {
        const content = fs.readFileSync(filePath, 'utf8');
        return JSON.parse(content);
      }
    } catch (error) {
      console.error('读取战斗日志失败:', error);
    }
    return null;
  }
}

export default new BattleLogger(); 